package org.dftproject.gedcom.core;

import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dftproject.gedcom.core.persistence.GedcomFactory;
import org.dftproject.genesis.core.collections.ICollectionDataProvider;
import org.dftproject.genesis.core.persistence.IMemento;
import org.dftproject.genesis.data.genealogy.GenealogyConstants;
import org.dftproject.genesis.data.genealogy.IPerson;
import org.dftproject.genesis.data.genealogy.ISource;
import org.dftproject.genesis.data.genealogy.impl.SourceImpl;
import org.dftproject.genesis.data.impl.AttributeImpl;

public class Gedcom extends AbstractGedcom implements ICollectionDataProvider {

	private final LinkedList<Line> lines = new LinkedList<Line>();
	private final Map<String, Line> records = new HashMap<String, Line>();
	
	private final Set<String> individuals = new HashSet<String>();
	private final Set<String> families = new HashSet<String>();
	
	private String path;

	public void load(String path) {
		this.path = path;
		
		GedcomReader reader = new GedcomReader();
		reader.addListener(new IGedcomReaderListener() {

			public void lineAdded(Line line) {				
				// Track lines with an XREF
				
				if (line.getId() != null) {
					records.put(line.getId(), line);
					
					// Track lines by record type
					
					if ("INDI".equals(line.getTag()))
						individuals.add(line.getId());
					else if ("FAM".equals(line.getTag()))
						families.add(line.getId());
				}
			}
			
		});
		
		FileReader fileReader = null;
		try {
			fileReader = new FileReader(path);
			lines.addAll(reader.read(fileReader));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fileReader != null) {
				try {
					fileReader.close();
				} catch (IOException e) {
				}
			}
		}
	}

	protected void addLine(Line line) {
		lines.add(line);
	}
	
	protected void printGedcom() {
		for (Line line : lines)
			printLine(line);
	}
	
	protected void printLine(Line line) {
		System.out.println(line);
		for (Line child : line.getChildren())
			printLine(child);
	}
	
	public Line getRecord(String id) {
		return records.get(id);
	}

	public List<IPerson> getPersons() {
		LinkedList<IPerson> persons = new LinkedList<IPerson>();

		for (String xref : individuals)
			persons.add(new GedcomPerson(this, xref, getRecord(xref)));

		return persons;
	}

	public List<Line> getLines() {
		return Collections.unmodifiableList(lines);
	}
	
	public ISource asSource(String id) {
		SourceImpl source = new SourceImpl();
		source.addAttribute(new AttributeImpl(GenealogyConstants.type, "org.dftproject.gedcom.source"));
		if (path != null)
			source.addAttribute(new AttributeImpl(GenealogyConstants.title, path));
		source.addAttribute(new AttributeImpl(GenealogyConstants.collection, this));
		source.addAttribute(new AttributeImpl("id", id));
		return source;
	}

	public String getFactoryId() {
		return GedcomFactory.ID;
	}

	public void saveState(IMemento memento) {
		memento.putString("path", path);
	}

}
